iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0

小明的現金與期約農業

今天要學習虛擬貨幣的現貨和期貨交易,這就像農業中的現金交易和期約交易。爸爸賣菜有兩種方式:一是現場賣給菜販(現貨),二是提前和餐廳簽約未來交貨(期貨)。兩種方式各有優缺點,讓我們來深入了解!

現貨交易 (Spot Trading)

現貨交易的特性

現貨交易就像在市場上直接買賣真實的貨物:

現貨交易的特性

現貨交易實作範例

class SpotTrading:
    """現貨交易系統"""
    
    def __init__(self, initial_balance=10000):
        self.balance = initial_balance
        self.holdings = {}  # {symbol: quantity}
        self.transaction_history = []
    
    def buy_spot(self, symbol, quantity, price):
        """買入現貨"""
        
        total_cost = quantity * price
        fee = total_cost * 0.001  # 0.1% 手續費
        
        if self.balance >= total_cost + fee:
            self.balance -= (total_cost + fee)
            
            if symbol in self.holdings:
                self.holdings[symbol] += quantity
            else:
                self.holdings[symbol] = quantity
            
            self.transaction_history.append({
                'type': 'buy',
                'symbol': symbol,
                'quantity': quantity,
                'price': price,
                'fee': fee,
                'timestamp': 'now'
            })
            
            return True, f"成功買入 {quantity} {symbol}"
        else:
            return False, "餘額不足"
    
    def sell_spot(self, symbol, quantity, price):
        """賣出現貨"""
        
        if symbol in self.holdings and self.holdings[symbol] >= quantity:
            total_value = quantity * price
            fee = total_value * 0.001
            net_receive = total_value - fee
            
            self.balance += net_receive
            self.holdings[symbol] -= quantity
            
            if self.holdings[symbol] == 0:
                del self.holdings[symbol]
            
            self.transaction_history.append({
                'type': 'sell',
                'symbol': symbol,
                'quantity': quantity,
                'price': price,
                'fee': fee,
                'timestamp': 'now'
            })
            
            return True, f"成功賣出 {quantity} {symbol}"
        else:
            return False, "持有量不足"
    
    def get_portfolio_value(self, current_prices):
        """計算投資組合總值"""
        
        portfolio_value = self.balance
        
        for symbol, quantity in self.holdings.items():
            if symbol in current_prices:
                portfolio_value += quantity * current_prices[symbol]
        
        return portfolio_value
    
    def calculate_unrealized_pnl(self, current_prices):
        """計算未實現損益"""
        
        unrealized_pnl = {}
        total_unrealized = 0
        
        for symbol, quantity in self.holdings.items():
            if symbol in current_prices:
                # 計算平均成本
                buy_transactions = [t for t in self.transaction_history 
                                  if t['symbol'] == symbol and t['type'] == 'buy']
                
                if buy_transactions:
                    total_cost = sum(t['quantity'] * t['price'] for t in buy_transactions)
                    total_quantity = sum(t['quantity'] for t in buy_transactions)
                    avg_cost = total_cost / total_quantity
                    
                    current_value = quantity * current_prices[symbol]
                    cost_basis = quantity * avg_cost
                    pnl = current_value - cost_basis
                    
                    unrealized_pnl[symbol] = {
                        'quantity': quantity,
                        'avg_cost': avg_cost,
                        'current_price': current_prices[symbol],
                        'unrealized_pnl': pnl,
                        'pnl_percentage': pnl / cost_basis if cost_basis > 0 else 0
                    }
                    
                    total_unrealized += pnl
        
        return unrealized_pnl, total_unrealized

# 使用示例
spot_trader = SpotTrading()

# 買入 BTC
spot_trader.buy_spot('BTC', 0.1, 50000)
spot_trader.buy_spot('ETH', 2, 3000)

# 查看投資組合
current_prices = {'BTC': 55000, 'ETH': 3200}
portfolio_value = spot_trader.get_portfolio_value(current_prices)
unrealized_pnl, total_pnl = spot_trader.calculate_unrealized_pnl(current_prices)

print(f"投資組合總值: ${portfolio_value:.2f}")
print(f"總未實現損益: ${total_pnl:.2f}")

期貨交易 (Futures Trading)

期貨交易的特性

期貨是標準化的未來交易合約:

期貨交易的特性

期貨交易實作範例

class FuturesTrading:
    """期貨交易系統"""
    
    def __init__(self, initial_balance=10000):
        self.balance = initial_balance
        self.positions = {}  # {symbol: {'side': 'long/short', 'size': quantity, 'entry_price': price}}
        self.used_margin = 0
        self.transaction_history = []
    
    def calculate_required_margin(self, symbol, size, price, leverage=10):
        """計算所需保證金"""
        notional_value = size * price
        required_margin = notional_value / leverage
        return required_margin
    
    def open_position(self, symbol, side, size, price, leverage=10):
        """開倉"""
        
        required_margin = self.calculate_required_margin(symbol, size, price, leverage)
        fee = size * price * 0.0004  # 0.04% 手續費
        
        available_balance = self.balance - self.used_margin
        
        if available_balance >= required_margin + fee:
            # 更新保證金使用
            self.used_margin += required_margin
            self.balance -= fee
            
            # 記錄部位
            position_key = f"{symbol}_{side}"
            if position_key in self.positions:
                # 加倉
                old_pos = self.positions[position_key]
                total_size = old_pos['size'] + size
                weighted_price = (old_pos['size'] * old_pos['entry_price'] + 
                                size * price) / total_size
                
                self.positions[position_key] = {
                    'side': side,
                    'size': total_size,
                    'entry_price': weighted_price,
                    'leverage': leverage,
                    'margin': old_pos['margin'] + required_margin
                }
            else:
                # 新倉
                self.positions[position_key] = {
                    'side': side,
                    'size': size,
                    'entry_price': price,
                    'leverage': leverage,
                    'margin': required_margin
                }
            
            self.transaction_history.append({
                'type': 'open',
                'symbol': symbol,
                'side': side,
                'size': size,
                'price': price,
                'leverage': leverage,
                'margin': required_margin,
                'fee': fee,
                'timestamp': 'now'
            })
            
            return True, f"成功開倉 {side} {size} {symbol}"
        else:
            return False, "保證金不足"
    
    def close_position(self, symbol, side, size, price):
        """平倉"""
        
        position_key = f"{symbol}_{side}"
        
        if position_key not in self.positions:
            return False, "無對應部位"
        
        position = self.positions[position_key]
        
        if position['size'] < size:
            return False, "平倉數量超過持倉"
        
        # 計算損益
        if side == 'long':
            pnl = size * (price - position['entry_price'])
        else:  # short
            pnl = size * (position['entry_price'] - price)
        
        # 計算手續費
        fee = size * price * 0.0004
        net_pnl = pnl - fee
        
        # 釋放保證金
        margin_released = (size / position['size']) * position['margin']
        self.used_margin -= margin_released
        
        # 更新餘額
        self.balance += net_pnl + margin_released
        
        # 更新部位
        if position['size'] == size:
            # 完全平倉
            del self.positions[position_key]
        else:
            # 部分平倉
            remaining_ratio = (position['size'] - size) / position['size']
            self.positions[position_key]['size'] -= size
            self.positions[position_key]['margin'] *= remaining_ratio
        
        self.transaction_history.append({
            'type': 'close',
            'symbol': symbol,
            'side': side,
            'size': size,
            'price': price,
            'pnl': pnl,
            'fee': fee,
            'net_pnl': net_pnl,
            'timestamp': 'now'
        })
        
        return True, f"平倉成功,淨損益: ${net_pnl:.2f}"
    
    def calculate_unrealized_pnl(self, current_prices):
        """計算未實現損益"""
        
        total_unrealized_pnl = 0
        position_details = {}
        
        for position_key, position in self.positions.items():
            symbol = position_key.split('_')[0]
            side = position['side']
            
            if symbol in current_prices:
                current_price = current_prices[symbol]
                entry_price = position['entry_price']
                size = position['size']
                
                if side == 'long':
                    unrealized_pnl = size * (current_price - entry_price)
                else:  # short
                    unrealized_pnl = size * (entry_price - current_price)
                
                total_unrealized_pnl += unrealized_pnl
                
                position_details[position_key] = {
                    'symbol': symbol,
                    'side': side,
                    'size': size,
                    'entry_price': entry_price,
                    'current_price': current_price,
                    'unrealized_pnl': unrealized_pnl,
                    'margin': position['margin']
                }
        
        return position_details, total_unrealized_pnl
    
    def check_margin_call(self, current_prices, maintenance_margin_ratio=0.5):
        """檢查保證金追繳"""
        
        _, unrealized_pnl = self.calculate_unrealized_pnl(current_prices)
        current_equity = self.balance + unrealized_pnl
        required_maintenance = self.used_margin * maintenance_margin_ratio
        
        if current_equity < required_maintenance:
            return True, f"保證金追繳警告!當前權益: ${current_equity:.2f}, 需要: ${required_maintenance:.2f}"
        
        return False, "保證金充足"

# 使用示例
futures_trader = FuturesTrading()

# 開多倉 BTC
success, msg = futures_trader.open_position('BTC', 'long', 1, 50000, leverage=10)
print(msg)

# 開空倉 ETH
futures_trader.open_position('ETH', 'short', 5, 3000, leverage=5)

# 檢查未實現損益
current_prices = {'BTC': 52000, 'ETH': 2900}
positions, total_pnl = futures_trader.calculate_unrealized_pnl(current_prices)
print(f"總未實現損益: ${total_pnl:.2f}")

# 檢查保證金狀況
margin_call, msg = futures_trader.check_margin_call(current_prices)
print(f"保證金狀況: {msg}")

現貨 vs 期貨 深度比較

風險報酬特性

風險報酬比較

交易策略適用性

class TradingStrategyComparison:
    """交易策略適用性比較"""
    
    def __init__(self):
        self.strategy_suitability = {
            'buy_and_hold': {
                'spot': 10,      # 最適合現貨
                'futures': 3,    # 不適合期貨(有到期日)
                'reason': '長期持有策略需要避免展倉成本'
            },
            'swing_trading': {
                'spot': 7,       # 適合現貨
                'futures': 8,    # 更適合期貨
                'reason': '中期交易可利用期貨的槓桿優勢'
            },
            'day_trading': {
                'spot': 5,       # 一般適合
                'futures': 9,    # 非常適合
                'reason': '日內交易適合利用期貨的高流動性和槓桿'
            },
            'scalping': {
                'spot': 6,       # 勉強適合
                'futures': 9,    # 非常適合
                'reason': '剝頭皮需要高頻交易和槓桿放大微利'
            },
            'arbitrage': {
                'spot': 8,       # 適合
                'futures': 9,    # 非常適合
                'reason': '套利策略需要靈活的做空能力'
            },
            'hedging': {
                'spot': 5,       # 有限適用
                'futures': 10,   # 完美適合
                'reason': '對沖需要衍生品工具'
            }
        }
    
    def get_recommendation(self, strategy, capital_size, risk_tolerance):
        """獲取策略建議"""
        
        strategy_info = self.strategy_suitability.get(strategy, {})
        
        recommendation = {
            'strategy': strategy,
            'spot_score': strategy_info.get('spot', 0),
            'futures_score': strategy_info.get('futures', 0),
            'reason': strategy_info.get('reason', ''),
        }
        
        # 根據資金規模調整建議
        if capital_size < 10000:
            recommendation['note'] = '小資金建議先從現貨開始學習'
        elif capital_size > 100000:
            recommendation['note'] = '大資金可考慮期貨提高資金效率'
        
        # 根據風險承受度調整
        if risk_tolerance == 'low':
            recommendation['futures_score'] *= 0.5
        elif risk_tolerance == 'high':
            recommendation['futures_score'] *= 1.2
        
        return recommendation

# 策略建議示例
comparator = TradingStrategyComparison()

strategies = ['buy_and_hold', 'day_trading', 'arbitrage']
for strategy in strategies:
    rec = comparator.get_recommendation(strategy, capital_size=50000, risk_tolerance='medium')
    print(f"\n{strategy}:")
    print(f"現貨適合度: {rec['spot_score']}/10")
    print(f"期貨適合度: {rec['futures_score']:.1f}/10")
    print(f"原因: {rec['reason']}")

期現套利實戰

基差分析

class BasisAnalysis:
    """基差分析工具"""
    
    def __init__(self):
        self.basis_history = []
    
    def calculate_basis(self, spot_price, futures_price, days_to_expiry):
        """計算基差和年化基差率"""
        
        basis = futures_price - spot_price
        basis_rate = basis / spot_price
        annualized_basis_rate = basis_rate * (365 / days_to_expiry)
        
        return {
            'basis': basis,
            'basis_rate': basis_rate,
            'annualized_basis_rate': annualized_basis_rate,
            'contango': basis > 0,  # 正價差(期貨>現貨)
            'backwardation': basis < 0  # 逆價差(期貨<現貨)
        }
    
    def identify_arbitrage_opportunity(self, spot_price, futures_price, 
                                     days_to_expiry, risk_free_rate=0.05):
        """識別套利機會"""
        
        basis_info = self.calculate_basis(spot_price, futures_price, days_to_expiry)
        
        # 理論期貨價格(考慮無風險利率)
        theoretical_futures = spot_price * (1 + risk_free_rate * days_to_expiry / 365)
        
        # 套利機會判斷
        if futures_price > theoretical_futures * 1.01:  # 期貨溢價>1%
            return {
                'opportunity': True,
                'strategy': 'sell_futures_buy_spot',
                'expected_profit': futures_price - theoretical_futures,
                'profit_rate': (futures_price - theoretical_futures) / spot_price,
                'action': '賣期貨,買現貨'
            }
        elif futures_price < theoretical_futures * 0.99:  # 期貨折價>1%
            return {
                'opportunity': True,
                'strategy': 'buy_futures_sell_spot',
                'expected_profit': theoretical_futures - futures_price,
                'profit_rate': (theoretical_futures - futures_price) / spot_price,
                'action': '買期貨,賣現貨'
            }
        else:
            return {
                'opportunity': False,
                'reason': '基差在合理範圍內'
            }

# 基差分析示例
basis_analyzer = BasisAnalysis()

# 分析套利機會
spot_price = 50000
futures_price = 50800
days_to_expiry = 30

opportunity = basis_analyzer.identify_arbitrage_opportunity(
    spot_price, futures_price, days_to_expiry
)

if opportunity['opportunity']:
    print(f"發現套利機會!")
    print(f"策略: {opportunity['action']}")
    print(f"預期利潤: ${opportunity['expected_profit']:.2f}")
    print(f"利潤率: {opportunity['profit_rate']:.2%}")
else:
    print(f"無套利機會: {opportunity['reason']}")

風險管理差異

現貨 vs 期貨風險控制

class RiskManagementComparison:
    """現貨與期貨風險管理比較"""
    
    def __init__(self):
        self.spot_risks = {
            'market_risk': '價格下跌風險,最大損失100%',
            'liquidity_risk': '流動性不足時難以快速出場',
            'custody_risk': '錢包安全、交易所風險',
            'regulatory_risk': '監管變化影響'
        }
        
        self.futures_risks = {
            'market_risk': '槓桿放大損失,可能超過本金',
            'liquidity_risk': '保證金追繳、強制平倉',
            'basis_risk': '現貨期貨價差變動風險',
            'rollover_risk': '展倉成本和時機風險',
            'counterparty_risk': '交易對手違約風險'
        }
    
    def calculate_risk_metrics(self, position_type, position_size, entry_price, 
                             current_price, leverage=1):
        """計算風險指標"""
        
        if position_type == 'spot':
            unrealized_pnl = position_size * (current_price - entry_price)
            max_loss = position_size * entry_price  # 最大損失為本金
            margin_requirement = position_size * entry_price
            
        else:  # futures
            if leverage > 1:
                notional_value = position_size * entry_price
                margin_requirement = notional_value / leverage
                unrealized_pnl = position_size * (current_price - entry_price)
                # 期貨最大損失可能超過保證金
                max_loss = float('inf')  # 理論上無限
            else:
                return self.calculate_risk_metrics('spot', position_size, 
                                                 entry_price, current_price, 1)
        
        return {
            'unrealized_pnl': unrealized_pnl,
            'pnl_percentage': unrealized_pnl / (position_size * entry_price),
            'margin_requirement': margin_requirement,
            'max_loss': max_loss,
            'leverage': leverage,
            'position_type': position_type
        }
    
    def recommend_stop_loss(self, position_type, leverage=1, risk_tolerance='medium'):
        """建議停損設定"""
        
        if position_type == 'spot':
            if risk_tolerance == 'low':
                return 0.05  # 5%
            elif risk_tolerance == 'medium':
                return 0.10  # 10%
            else:
                return 0.15  # 15%
        
        else:  # futures
            base_stop = self.recommend_stop_loss('spot', 1, risk_tolerance)
            adjusted_stop = base_stop / leverage  # 槓桿越高,停損越嚴格
            return max(adjusted_stop, 0.02)  # 最少2%

# 風險比較示例
risk_manager = RiskManagementComparison()

# 比較現貨和期貨風險
spot_metrics = risk_manager.calculate_risk_metrics(
    'spot', 1, 50000, 48000
)

futures_metrics = risk_manager.calculate_risk_metrics(
    'futures', 1, 50000, 48000, leverage=10
)

print("現貨交易風險:")
print(f"未實現損益: ${spot_metrics['unrealized_pnl']:.2f}")
print(f"損益百分比: {spot_metrics['pnl_percentage']:.2%}")
print(f"保證金需求: ${spot_metrics['margin_requirement']:.2f}")

print("\n期貨交易風險:")
print(f"未實現損益: ${futures_metrics['unrealized_pnl']:.2f}")
print(f"損益百分比: {futures_metrics['pnl_percentage']:.2%}")
print(f"保證金需求: ${futures_metrics['margin_requirement']:.2f}")

# 停損建議
spot_stop = risk_manager.recommend_stop_loss('spot', risk_tolerance='medium')
futures_stop = risk_manager.recommend_stop_loss('futures', leverage=10, risk_tolerance='medium')

print(f"\n停損建議:")
print(f"現貨停損: {spot_stop:.1%}")
print(f"期貨停損: {futures_stop:.1%}")

小結

今天我們深入比較了虛擬貨幣的現貨和期貨交易,就像比較現金買賣和期約交易的差異。重要要點:

現貨交易特點:

  • 資金需求高但風險相對可控
  • 適合長期投資和初學者
  • 無時間壓力,可長期持有
  • 享有實際資產所有權

期貨交易特點:

  • 槓桿效應,資金效率高
  • 風險大但機會也大
  • 適合短期交易和專業投資者
  • 需要主動管理和風險控制

選擇建議:

  • 新手從現貨開始學習
  • 有經驗後可嘗試期貨
  • 根據策略類型選擇工具
  • 嚴格執行風險管理

風險控制重點:

  • 現貨重點是倉位控制
  • 期貨重點是槓桿控制
  • 都需要設定停損機制
  • 持續監控和調整

明天我們將學習合約中的槓桿與資金費率,進一步了解期貨交易的細節!


下一篇:Day 21 - 合約中的槓桿與現金費率


上一篇
Day 19: 對沖的風險與報酬探討
下一篇
Day 21: 合約中的槓桿與現金費率
系列文
小資族的量化交易 10123
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言